package main

import "fmt"

// 假设一开始业务需要两种发送信息的渠道，sms和email，我们可以分别实现sms和email两个接口。
// 之后随着业务迭代，又产生了新的需求，需要提供两种系统发送方式，systemA和systemB，
// 并且这两种系统发送方式都应该支持sms和email渠道。
// 此时至少需要提供4种方法：systemA to sms，systemA to email，systemB to sms，systemB to email。

type SendMessage interface {
	send(text, to string)
}

type sms struct{}

func NewSms() SendMessage {
	return &sms{}
}

func (*sms) send(text, to string) {
	fmt.Printf("send %s to %s sms", text, to)
}

type email struct{}

func NewEmail() SendMessage {
	return &email{}
}

func (*email) send(text, to string) {
	fmt.Printf("send %s to %s email", text, to)
}

type systemA struct {
	method SendMessage
}

func NewSystemA(method SendMessage) *systemA {
	return &systemA{
		method: method,
	}
}

func (m *systemA) SendMessage(text, to string) {
	m.method.send(fmt.Sprintf("systemA %s", text), to)
}

type systemB struct {
	method SendMessage
}

func NewSystemB(method SendMessage) *systemB {
	return &systemB{
		method: method,
	}
}

func (m *systemB) SendMessage(text, to string) {
	m.method.send(fmt.Sprintf("systemB %s", text), to)
}

func ExampleSystemA() {
	NewSystemA(NewSms()).SendMessage("hello", "123")
	NewSystemA(NewEmail()).SendMessage("hello", "123")
}

func ExampleSystemB() {
	NewSystemB(NewSms()).SendMessage("hello", "123")
	NewSystemB(NewEmail()).SendMessage("hello", "123")
}
